package commondao

import (
	"admin100/app/dao/centerdao"
	"admin100/app/service/centerservice"
	"admin100/library/define"
	"admin100/library/define/defErr"
	"database/sql"
	"fmt"
	"strings"

	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/text/gstr"
	"github.com/jinzhu/gorm"
)

var DB = &customDBDao{}

type customDBDao struct{}

/*
 * 实例一个gdb.DB,默认池连接,正常讲性能ok，待后续测试
 */
func (s *customDBDao) NewCustomGdb(nodeStr string) gdb.DB {
	if gstr.Trim(nodeStr) == "" {
		defErr.Panic(define.NodeNameEmpty)
	}

	node, err := centerdao.CServerNode.Where(centerdao.CServerNode.Columns.Node, nodeStr).FindOne()
	if node == nil {
		defErr.Panic(define.GameNodeDbErrLink, nodeStr)
	}
	defErr.IfPanic(err, define.DataOptFail)
	if node == nil {
		defErr.Panic(define.RecordNodFound)
	}

	parseArr := strings.Split(node.Node, "@")
	if len(parseArr) != 2 {
		defErr.Panic(define.NodeNameParseFail, node.Node)
	}
	var (
		ip           = node.DbHost
		port         = node.DbPort
		databaseName = node.DbName
		password     = g.Cfg().GetString("database.game.pass")
	)

	var groupName = databaseName
	config := gdb.ConfigNode{
		Type:             "mysql",
		Name:             databaseName,
		Debug:            true,
		DryRun:           false,
		Charset:          "utf8",
		LinkInfo:         fmt.Sprintf("root:%s@tcp(%s:%d)/%s", password, ip, port, databaseName),
		MaxIdleConnCount: 30,
		MaxOpenConnCount: 50,
		MaxConnLifeTime:  3600,
	}

	if gdb.GetConfig(groupName) == nil {
		gdb.AddConfigNode(groupName, config)
	}
	db, err := gdb.New(groupName)
	defErr.IfPanic(err, define.DataOptFail, node.Node+" parse : "+config.LinkInfo)

	err = db.PingMaster()
	if err != nil {
		defErr.Panic(define.LinkServerFail, err.Error()+" -> data node : "+node.Node+" , parse is : "+config.LinkInfo)
	}

	return db
}

// 通过node获取 gorm.DB 实例
func (s *customDBDao) getGameDbgOrmByNode(nodeStr string) *gorm.DB {
	if gstr.Trim(nodeStr) == "" {
		defErr.Panic(define.NodeNameEmpty)
	}

	node, err := centerdao.CServerNode.Where(centerdao.CServerNode.Columns.Node, nodeStr).FindOne()
	if err == sql.ErrNoRows {
		defErr.Panic(define.GameNodeDbErrLink, nodeStr)
	}
	defErr.IfPanic(err, define.DataOptFail)

	parseArr := strings.Split(node.Node, "@")
	if len(parseArr) != 2 {
		defErr.Panic(define.NodeNameParseFail, node.Node)
	}
	//gameDbName := "game_" + array[0]
	gameDbName := node.DbName
	gameDbHost := node.DbHost
	gameDbPort := node.DbPort
	gameDbPwd := g.Cfg().GetString("database.game.pass")
	dbArgs := fmt.Sprintf("root:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", gameDbPwd, gameDbHost, gameDbPort, gameDbName)
	//dbArgs := "root:game1234@tcp(" + serverNode.Ip + ":3306)/" + gameDbName +"?charset=utf8&parseTime=True&loc=Local"
	gameDb, gErr := gorm.Open("mysql", dbArgs)
	defErr.IfPanic(gErr, define.DataOptFail, node.Node+" parse : "+dbArgs)
	gameDb.SingularTable(true)

	return gameDb
}

//  通过node str获取DB
func (s *customDBDao) NewGameDbByNodeStr(nodeStr string) gdb.DB {
	if gstr.Trim(nodeStr) == "" {
		defErr.Panic(define.NodeNameEmpty)
	}
	return s.NewCustomGdb(nodeStr)
}

// 通过平台id和区服id获取DB
func (s *customDBDao) NewGameDbByPtIdAndSid(ptId, sid string) gdb.DB {

	if gstr.Trim(ptId) == "" {
		defErr.Panic(define.NodeNameEmpty)
	}
	if gstr.Trim(sid) == "" {
		defErr.Panic(define.NodeServerEmpty)
	}
	sNode := centerservice.CGameServer.FetchNodeStrByPtIdAndSid(ptId, sid)
	return s.NewCustomGdb(sNode)
}

// 通过平台id和区服id获取DB
func (s *customDBDao) NewGOrmDbByPtIdAndSid(ptId, sid string) *gorm.DB {
	if gstr.Trim(ptId) == "" {
		defErr.Panic(define.NodeNameEmpty)
	}
	if gstr.Trim(sid) == "" {
		defErr.Panic(define.NodeServerEmpty)
	}
	sNode := centerservice.CGameServer.FetchNodeStrByPtIdAndSid(ptId, sid)
	return s.getGameDbgOrmByNode(sNode)
}
